package sw6.admin.gui.logic;

import java.io.*;
import java.util.ArrayList;

import javax.xml.parsers.*;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.*;

public class SettingParser {

	private static final String ROOT  = "settings";
	private static final String VISIBLE = "visible";
	private static final String MENU = "menu";

	private static final String INTEGER = "integer";
	private static final String STRING = "string";
	private static final String BOOLEAN = "boolean";
	private static final String DOUBLE = "double";
	private static final String OBJECT = "object";
	private static final String ENUM = "enum";
	private static final String ENUM_ELEMENT = "element";

	private static final String VARIABLE_NAME = "varName";
	private static final String REAL_NAME = "realName";
	private static final String DESCRIPTION = "desc";
	private static final String MENU_TITLE = "title";
	private static final String CLASS_PATH = "classPath";
	private static final String MIN = "min";
	private static final String MAX= "max";


	public static Menu LoadXML(String path) throws SAXException, IOException
	{
		InputStream inputStream = null;
		File inFile = new File(path);
		inputStream = new FileInputStream(inFile);

		return LoadXML(inputStream);
	}

	public static Menu LoadXML(InputStream inputStream) throws SAXException, IOException {
		// Setup the XML DOM parser
		DocumentBuilderFactory dbf 	= DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder	= null;
		try {
			docBuilder = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}

		Document doc 			= null;

		doc 		= docBuilder.parse(inputStream);

		Element start =  ((Element)((Element) doc.getElementsByTagName(ROOT).item(0)).getElementsByTagName(VISIBLE).item(0));
		Menu rootMenu = new Menu("ROOT", "ROOT");

		if (start != null)
			handleMenu(rootMenu, start);

		return rootMenu;
	}

	private static void handleMenu(Menu menu, Element menuElement)
	{
		NodeList nodes = menuElement.getChildNodes();

		ArrayList<Element> integers = new ArrayList<Element>();
		ArrayList<Element> strings = new ArrayList<Element>();
		ArrayList<Element> doubles = new ArrayList<Element>();
		ArrayList<Element> booleans = new ArrayList<Element>();
		ArrayList<Element> objects = new ArrayList<Element>();
		ArrayList<Element> menues = new ArrayList<Element>();
		ArrayList<Element> enums = new ArrayList<Element>();

		for (int i = 0; i < nodes.getLength(); i++) {
			if (nodes.item(i).getNodeName().equalsIgnoreCase(INTEGER)) {
				integers.add((Element) nodes.item(i));
			}
			if (nodes.item(i).getNodeName().equalsIgnoreCase(STRING)) {
				strings.add((Element) nodes.item(i));
			}
			if (nodes.item(i).getNodeName().equalsIgnoreCase(DOUBLE)) {
				doubles.add((Element) nodes.item(i));
			}
			if (nodes.item(i).getNodeName().equalsIgnoreCase(BOOLEAN)) {
				booleans.add((Element) nodes.item(i));
			}
			if (nodes.item(i).getNodeName().equalsIgnoreCase(OBJECT)) {
				objects.add((Element) nodes.item(i));
			}
			if (nodes.item(i).getNodeName().equalsIgnoreCase(MENU)) {
				menues.add((Element) nodes.item(i));
			}
			if (nodes.item(i).getNodeName().equalsIgnoreCase(ENUM)) {
				enums.add((Element) nodes.item(i));
			}
		}

		handleElements(integers, menu, INTEGER);
		handleElements(strings, menu, STRING);
		handleElements(doubles, menu, DOUBLE);
		handleElements(booleans, menu, BOOLEAN);
		handleElements(objects, menu, OBJECT);
		handleElements(enums, menu, ENUM);

		for (int i = 0; i < menues.size(); i++) {
			Element newMenuElement = (Element) menues.get(i);
			String realName = newMenuElement.getAttribute(MENU_TITLE);
			String description = newMenuElement.getAttribute(DESCRIPTION);

			Menu newMenu = new Menu(realName, description);
			menu.addMenu(newMenu);
			handleMenu(newMenu, newMenuElement);
		}
	}

	private static void handleElements(ArrayList<Element> nodeList, Menu menu, String type) {
		for (int i = 0; i < nodeList.size(); i++) {
			Element e = (Element)nodeList.get(i);
			String varName = e.getAttribute(VARIABLE_NAME);
			String realName = e.getAttribute(REAL_NAME);
			String description = e.getAttribute(DESCRIPTION);
			String classPath = e.getAttribute(CLASS_PATH);
			
			if (realName.equals(""))
				realName = varName;

			double min = -Double.MAX_VALUE;
			double max = Double.MAX_VALUE;
			if (e.hasAttribute(MIN)) {
				min = Double.valueOf(e.getAttribute(MIN).trim()).doubleValue();
			}
			if (e.hasAttribute(MAX)) {
				max = Double.valueOf(e.getAttribute(MAX).trim()).doubleValue();
			}

			if (type.equals(ENUM)) {
				ArrayList<SettingEnumElement> enumElements = new ArrayList<SettingEnumElement>();
				NodeList nodes = e.getChildNodes();

				for (int j = 0; j < nodes.getLength(); j++)  {
					if (nodes.item(j).getNodeName().equalsIgnoreCase(ENUM_ELEMENT))
					{
						Element element = (Element)nodes.item(j);
						String enumRealName = element.getAttribute(REAL_NAME);
						enumElements.add(new SettingEnumElement(enumRealName));
					}
				}

				Setting setting = new Setting(type, realName, varName, description, classPath, min, max);
				setting.setEnumElements(enumElements);
				menu.addSetting(setting);
				continue;
			}

			menu.addSetting(new Setting(type, realName, varName, description, classPath, min, max));
		}
	}
}
